çŸä»£çãªåã·ã¹ãã ã®å éšåäœãæ¢ããŸããå¶åŸ¡ãããŒè§£æïŒCFAïŒããããå®å šã§å ç¢ãªã³ãŒããå®çŸãã匷åãªåçµãèŸŒã¿æè¡ãããã«ããŠå¯èœã«ããããåŠã³ãŸãããã
ã³ã³ãã€ã©ã¯ããã«ããŠè³¢ããªãã®ãïŒåçµã蟌ã¿ãšå¶åŸ¡ãããŒè§£æã®è©³çŽ°è§£èª¬
éçºè ãšããŠãç§ãã¡ã¯åžžã«ããŒã«ã®éããªç¥æ§ãšå¯Ÿè©±ããŠããŸããã³ãŒããæžããšãIDEã¯å³åº§ã«ãªããžã§ã¯ãã§å©çšå¯èœãªã¡ãœãããææ¡ããŸãã倿°ããªãã¡ã¯ã¿ãªã³ã°ãããšããã¡ã€ã«ãä¿åããåã§ãããåãã§ãã«ãŒãæœåšçãªå®è¡æãšã©ãŒãèŠåããŠãããŸããããã¯éæ³ã§ã¯ãããŸãããããã¯æŽç·Žãããéçè§£æã®çµæã§ããããã®æã匷åã§ãŠãŒã¶ãŒåãã®æ©èœã®1ã€ãåçµã蟌ã¿ã§ãã
stringãŸãã¯numberã«ãªããã倿°ãæ±ã£ãããšã¯ãããŸããïŒãããããæäœãå®è¡ããåã«ãã®åããã§ãã¯ããããã«ifæãæžããããšã§ãããããã®ãããã¯å
ã§ã¯ãèšèªã¯å€æ°ãstringã§ããããšããç¥ã£ãŠããããæåååºæã®ã¡ãœãããè§£æŸããäŸãã°æ°å€ã«å¯ŸããŠ.toUpperCase()ãåŒã³åºãããšããããšãé²ããŸããç¹å®ã®ã³ãŒããã¹å
ã§åãã€ã³ããªãžã§ã³ãã«æŽç·Žãããããšããããåçµã蟌ã¿ã§ãã
ããããã³ã³ãã€ã©ãåãã§ãã«ãŒã¯ã©ã®ããã«ããŠãããéæããŠããã®ã§ããããïŒãã®äžå¿çãªã¡ã«ããºã ã¯ãã³ã³ãã€ã©çè«ã«ããã匷åãªãã¯ããã¯ã§ããå¶åŸ¡ãããŒè§£æïŒControl Flow Analysis, CFAïŒã§ãããã®èšäºã§ã¯ããã®ããã»ã¹ã®è£åŽãæããã«ããŸããåçµã蟌ã¿ãšã¯äœããå¶åŸ¡ãããŒè§£æãã©ã®ããã«æ©èœããããæ¢ããæŠå¿µçãªå®è£ ãé ã远ã£ãŠèŠãŠãããŸãããã®è©³çްãªè§£èª¬ã¯ã奜å¥å¿æºçãªéçºè ãã³ã³ãã€ã©ãšã³ãžãã¢ãç®æã人ããããã¯çŸä»£ã®ããã°ã©ãã³ã°èšèªãããã»ã©å®å šã§çç£çã«ããŠããæŽç·Žãããããžãã¯ãçè§£ããããšé¡ããã¹ãŠã®äººã®ããã®ãã®ã§ãã
åçµã蟌ã¿ãšã¯äœãïŒå®è·µçå ¥é
ãã®æ žå¿ã«ãããŠãåçµã蟌ã¿ïŒåæŽç·ŽããããŒã¿ã€ãã³ã°ãšãåŒã°ããïŒã¯ãéçåãã§ãã«ãŒããã³ãŒãã®ç¹å®ã®é åå ã§ã宣èšãããåãããå ·äœçãªåã倿°ã«å¯ŸããŠæšè«ããããã»ã¹ã§ããå ±çšäœã®ãããªåºç¯ãªåãåããè«ççãªãã§ãã¯ãä»£å ¥ã«åºã¥ããŠããããçµã蟌ã¿ããŸãã
TypeScriptã®æç¢ºãªæ§æã䜿çšããŠãããã€ãã®äžè¬çãªäŸãèŠãŠã¿ãŸãããããã ãããã®ååã¯PythonïŒMypyã䜿çšïŒãKotlinãªã©å€ãã®çŸä»£èšèªã«é©çšãããŸãã
äžè¬çãªçµã蟌ã¿ãã¯ããã¯
-
`typeof`ã¬ãŒã: ããã¯æãå€å
žçãªäŸã§ãã倿°ã®ããªããã£ãåããã§ãã¯ããŸãã
äŸ:
function processInput(input: string | number) {
if (typeof input === 'string') {
// ãã®ãããã¯å ã§ã¯ã'input'ã¯stringåã§ããããšãããã£ãŠããŸãã
console.log(input.toUpperCase()); // ããã¯å®å šã§ãïŒ
} else {
// ãã®ãããã¯å ã§ã¯ã'input'ã¯numberåã§ããããšãããã£ãŠããŸãã
console.log(input.toFixed(2)); // ãããå®å šã§ãïŒ
}
} -
`instanceof`ã¬ãŒã: ã³ã³ã¹ãã©ã¯ã¿é¢æ°ãã¯ã©ã¹ã«åºã¥ããŠãªããžã§ã¯ãã®åãçµã蟌ãããã«äœ¿çšãããŸãã
äŸ:
class User { constructor(public name: string) {} }
class Guest { constructor() {} }
function greet(person: User | Guest) {
if (person instanceof User) {
// 'person'ã¯Useråã«çµã蟌ãŸããŸãã
console.log(`Hello, ${person.name}!`);
} else {
// 'person'ã¯Gueståã«çµã蟌ãŸããŸãã
console.log('Hello, guest!');
}
} -
Truthinessãã§ãã¯: `null`ã`undefined`ã`0`ã`false`ããŸãã¯ç©ºæååãé€å€ããããã®äžè¬çãªãã¿ãŒã³ã§ãã
äŸ:
function printName(name: string | null | undefined) {
if (name) {
// 'name'ã¯'string | null | undefined'ããåãªã'string'ã«çµã蟌ãŸããŸãã
console.log(name.length);
}
} -
ç䟡æ§ããã³ããããã£ã¬ãŒã: ç¹å®ã®ãªãã©ã«å€ããã§ãã¯ããããããããã£ã®ååšã確èªãããããããšã§ããç¹ã«å€å¥å¯èœãªå
±çšäœã«ãããŠåãçµã蟌ãããšãã§ããŸãã
äŸïŒå€å¥å¯èœãªå ±çšäœïŒ:
interface Circle { kind: 'circle'; radius: number; }
interface Square { kind: 'square'; sideLength: number; }
type Shape = Circle | Square;
function getArea(shape: Shape) {
if (shape.kind === 'circle') {
// 'shape'ã¯Circleã«çµã蟌ãŸããŸãã
return Math.PI * shape.radius ** 2;
} else {
// 'shape'ã¯Squareã«çµã蟌ãŸããŸãã
return shape.sideLength ** 2;
}
}
ãã®å©ç¹ã¯çµ¶å€§ã§ããã³ã³ãã€ã«æã®å®å šæ§ãæäŸããå€§èŠæš¡ãªã¯ã©ã¹ã®å®è¡æãšã©ãŒãé²ããŸããããè¯ããªãŒãã³ã³ããªãŒãã§éçºè äœéšãåäžãããã³ãŒããããèªå·±ææžåããããããŸããåé¡ã¯ãåãã§ãã«ãŒããã®æèèªèãã©ã®ããã«æ§ç¯ããŠããã®ãããšããããšã§ãã
éæ³ã®è£ã«ãããšã³ãžã³ïŒå¶åŸ¡ãããŒè§£æïŒCFAïŒã®çè§£
å¶åŸ¡ãããŒè§£æã¯ãã³ã³ãã€ã©ãåãã§ãã«ãŒãããã°ã©ã ãåãããå¯èœæ§ã®ããå®è¡ãã¹ãçè§£ã§ããããã«ããéçè§£ææè¡ã§ããã³ãŒããå®è¡ããã®ã§ã¯ãªãããã®æ§é ãåæããŸãããã®ããã«äœ¿çšãããäž»èŠãªããŒã¿æ§é ã¯ãå¶åŸ¡ãããŒã°ã©ãïŒCFGïŒã§ãã
å¶åŸ¡ãããŒã°ã©ãïŒCFGïŒãšã¯äœãïŒ
CFGã¯ãããã°ã©ã ã®å®è¡äžã«ééããå¯èœæ§ã®ãããã¹ãŠã®ãã¹ã衚ãæåã°ã©ãã§ããããã¯ä»¥äžã§æ§æãããŸãïŒ
- ããŒãïŒãŸãã¯åºæ¬ãããã¯ïŒ: æåãšæåŸãé€ããŠãå å€ãžã®åå²ããªãäžé£ã®é£ç¶ããæãå®è¡ã¯åžžã«ãããã¯ã®æåã®æããå§ãŸãã忢ãããåå²ãããããããšãªãæåŸã®æãŸã§é²ã¿ãŸãã
- ãšããž: ãããã¯åºæ¬ãããã¯éã®å¶åŸ¡ã®æµããã€ãŸãããžã£ã³ããã衚ããŸããäŸãã°ã`if`æã¯2ã€ã®åºåãšããžãæã€ããŒããäœæããŸãã1ã€ã¯ãtrueããã¹çšããã1ã€ã¯ãfalseããã¹çšã§ãã
ç°¡åãª`if-else`æã®CFGãèŠèŠåããŠã¿ãŸãããïŒ
let x: string | number = ...;
if (typeof x === 'string') { // ãããã¯AïŒæ¡ä»¶ïŒ
console.log(x.length); // ãããã¯BïŒTrueåå²ïŒ
} else {
console.log(x + 1); // ãããã¯CïŒFalseåå²ïŒ
}
console.log('Done'); // ãããã¯DïŒåæµç¹ïŒ
æŠå¿µçãªCFGã¯æ¬¡ã®ããã«ãªããŸãïŒ
[ ãšã³ã㪠] --> [ ãããã¯A: `typeof x === 'string'` ] --> (trueãšããž) --> [ ãããã¯B ] --> [ ãããã¯D ]
\-> (falseãšããž) --> [ ãããã¯C ] --/
CFAã¯ããã®ã°ã©ãããæ©ãããåããŒãã§æ å ±ã远跡ããããšãå«ã¿ãŸããåçµã蟌ã¿ã®å Žåãç§ãã¡ã远跡ããæ å ±ã¯å倿°ã®å¯èœãªåã®éåã§ãããšããžäžã®æ¡ä»¶ãåæããããšã§ããããã¯ãããããã¯ãžç§»åããéã«ãã®åæ å ±ãæŽæ°ã§ããŸãã
åçµã蟌ã¿ã®ããã®å¶åŸ¡ãããŒè§£æã®å®è£ ïŒæŠå¿µçãŠã©ãŒã¯ã¹ã«ãŒ
çµã蟌ã¿ã®ããã«CFAã䜿çšããåãã§ãã«ãŒãæ§ç¯ããããã»ã¹ãåè§£ããŠã¿ãŸããããRustãC++ã§ã®å®éã®å®è£ ã¯éåžžã«è€éã§ãããäžå¿çãªæŠå¿µã¯çè§£å¯èœã§ãã
ã¹ããã1ïŒå¶åŸ¡ãããŒã°ã©ãïŒCFGïŒã®æ§ç¯
ããããã³ã³ãã€ã©ã®æåã®ã¹ãããã¯ããœãŒã¹ã³ãŒããæœè±¡æ§ææšïŒASTïŒã«è§£æããããšã§ããASTã¯ã³ãŒãã®æ§ææ§é ã衚ããŸããCFGã¯ãã®ASTããæ§ç¯ãããŸãã
CFGãæ§ç¯ããã¢ã«ãŽãªãºã ã¯éåžžã以äžãå«ã¿ãŸãïŒ
- åºæ¬ãããã¯ã®ãªãŒããŒã®ç¹å®ïŒ æããªãŒããŒïŒæ°ããåºæ¬ãããã¯ã®éå§ïŒã§ããã®ã¯ã次ã®å Žåã§ãïŒ
- ããã°ã©ã ã®æåã®æã§ããã
- åå²ã®ã¿ãŒã²ããã§ããïŒäŸïŒ`if`ã`else`ãããã¯å ã®ã³ãŒããã«ãŒãã®éå§ïŒã
- åå²ãŸãã¯returnæã®çŽåŸã®æã§ããã
- ãããã¯ã®æ§ç¯ïŒ åãªãŒããŒã«å¯ŸããŠããã®åºæ¬ãããã¯ã¯ãªãŒããŒèªäœãšã次ã®ãªãŒããŒãŸã§ïŒãã ããæ¬¡ã®ãªãŒããŒã¯å«ãŸãªãïŒã®ãã¹ãŠã®åŸç¶ã®æã§æ§æãããŸãã
- ãšããžã®è¿œå ïŒ ãããŒã衚ãããã«ãããã¯éã«ãšããžãæãããŸãã`if (condition)`ã®ãããªæ¡ä»¶æã¯ãæ¡ä»¶ã®ãããã¯ãããtrueããããã¯ãžã®ãšããžãšããfalseããããã¯ïŒãŸãã¯`else`ããªãå Žåã¯çŽåŸã®ãããã¯ïŒãžã®å¥ã®ãšããžãäœæããŸãã
ã¹ããã2ïŒç¶æ 空é - åæ å ±ã®è¿œè·¡
ã¢ãã©ã€ã¶ãCFGãèµ°æ»ããéãåãã€ã³ãã§ãç¶æ ããç¶æããå¿ èŠããããŸããåçµã蟌ã¿ã®å Žåããã®ç¶æ ã¯æ¬è³ªçã«ãã¹ã³ãŒãå ã®å倿°ããã®çŸåšã®ããããçµã蟌ãŸããåã«é¢é£ä»ããããããŸãã¯èŸæžã§ãã
// ã³ãŒãã®ç¹å®ã®ãã€ã³ãã«ãããæŠå¿µçãªç¶æ
interface TypeState {
[variableName: string]: Type;
}
è§£æã¯ãå倿°ã宣èšãããåãæã€åæç¶æ
ã§ã颿°ãŸãã¯ããã°ã©ã ã®ãšã³ããªãã€ã³ãããå§ãŸããŸããå
ã®äŸã§ã¯ãåæç¶æ
ã¯{ x: String | Number }ãšãªããŸãããã®ç¶æ
ã¯ã°ã©ããéããŠäŒæãããŸãã
ã¹ããã3ïŒæ¡ä»¶ã¬ãŒãã®åæïŒäžæ žããžãã¯ïŒ
ããã§çµã蟌ã¿ãè¡ãããŸããã¢ãã©ã€ã¶ãæ¡ä»¶åå²ïŒ`if`ã`while`ããŸãã¯`switch`ã®æ¡ä»¶ïŒã衚ãããŒãã«ééãããšãæ¡ä»¶èªäœã調ã¹ãŸããæ¡ä»¶ã«åºã¥ããŠã2ã€ã®ç°ãªãåºåç¶æ ãäœæããŸãã1ã€ã¯æ¡ä»¶ãçã§ãããã¹çšããã1ã€ã¯æ¡ä»¶ãåœã§ãããã¹çšã§ãã
ã¬ãŒãtypeof x === 'string'ãåæããŠã¿ãŸãããïŒ
-
ãTrueãåå²ïŒ ã¢ãã©ã€ã¶ã¯ãã®ãã¿ãŒã³ãèªèããŸãããã®åŒãçã§ããå Žåã`x`ã®åã¯`string`ã§ãªããã°ãªããªãããšãç¥ã£ãŠããŸãããããã£ãŠãããããæŽæ°ããŠãtrueããã¹çšã®æ°ããç¶æ
ãäœæããŸãïŒ
å ¥åç¶æ ïŒ
{ x: String | Number }Trueãã¹ã®åºåç¶æ ïŒ
ãã®æ°ããããæ£ç¢ºãªç¶æ ã¯ãtrueåå²ã®æ¬¡ã®ãããã¯ïŒãããã¯BïŒã«äŒæãããŸãããããã¯Bå ã§ã¯ã`x`ã«å¯Ÿããä»»æã®æäœã¯`String`åã«å¯ŸããŠãã§ãã¯ãããŸãã{ x: String } -
ãFalseãåå²ïŒ ãããåæ§ã«éèŠã§ãã
typeof x === 'string'ãåœã§ããå Žåãããã¯`x`ã«ã€ããŠäœãæããŠãããã§ããããïŒã¢ãã©ã€ã¶ã¯å ã®åãããtrueãã®åãå·®ãåŒãããšãã§ããŸããå ¥åç¶æ ïŒ
{ x: String | Number }åé€ããåïŒ
StringFalseãã¹ã®åºåç¶æ ïŒ
ãã®æŽç·Žãããç¶æ ã¯ããfalseããã¹ãäžã£ãŠãããã¯Cã«äŒæãããŸãããããã¯Cå ã§ã¯ã`x`ã¯æ£ãã`Number`ãšããŠæ±ãããŸãã{ x: Number }ïŒ(String | Number) - String = Numberãªã®ã§ïŒ
ã¢ãã©ã€ã¶ã¯ãããŸããŸãªãã¿ãŒã³ãçè§£ããããã®çµã¿èŸŒã¿ããžãã¯ãæã£ãŠããå¿ èŠããããŸãïŒ
x instanceof CïŒtrueãã¹ã§ã¯ã`x`ã®åã¯`C`ã«ãªããŸããfalseãã¹ã§ã¯ãå ã®åã®ãŸãŸã§ããx != nullïŒtrueãã¹ã§ã¯ã`Null`ãš`Undefined`ã`x`ã®åããåé€ãããŸããshape.kind === 'circle'ïŒ`shape`ãå€å¥å¯èœãªå ±çšäœã§ããå Žåããã®åã¯`kind`ããªãã©ã«å`'circle'`ã§ããã¡ã³ããŒã«çµã蟌ãŸããŸãã
ã¹ããã4ïŒå¶åŸ¡ãããŒãã¹ã®åæµ
ç§ãã¡ã®`if-else`æã®åŸããããã¯Dã®ããã«åå²ãååæµãããšããäœãèµ·ããã§ããããïŒã¢ãã©ã€ã¶ã¯ããã®åæµç¹ã«å°éãã2ã€ã®ç°ãªãç¶æ ãæã£ãŠããŸãïŒ
- ãããã¯BããïŒtrueãã¹ïŒïŒ
{ x: String } - ãããã¯CããïŒfalseãã¹ïŒïŒ
{ x: Number }
ãããã¯Dã®ã³ãŒãã¯ãã©ã¡ãã®ãã¹ãåããããã«é¢ãããæå¹ã§ãªããã°ãªããŸããããããä¿èšŒãããããã¢ãã©ã€ã¶ã¯ãããã®ç¶æ ãåæµãããå¿ èŠããããŸããå倿°ã«ã€ããŠããã¹ãŠã®å¯èœæ§ãå å«ããæ°ããåãèšç®ããŸããããã¯éåžžããã¹ãŠã®å ¥ã£ãŠãããã¹ããã®åã®å ±çšäœïŒunionïŒãåãããšã§è¡ãããŸãã
ãããã¯Dã®åæµåŸã®ç¶æ
ïŒ { x: Union(String, Number) } ããã¯{ x: String | Number }ã«åçŽåãããŸãã
ããã°ã©ã ã®ãã®æç¹ã§ã¯ãã©ã¡ãã®åå²ããæ¥ãå¯èœæ§ãããããã`x`ã®åã¯å ã®ããåºç¯ãªåã«æ»ããŸãããããã`if-else`ãããã¯ã®åŸã«`x.toUpperCase()`ã䜿çšã§ããªãçç±ã§ãâåå®å šæ§ã®ä¿èšŒã倱ãããŠããã®ã§ãã
ã¹ããã5ïŒã«ãŒããšä»£å ¥ã®åŠç
-
代å
¥ïŒ 倿°ãžã®ä»£å
¥ã¯CFAã«ãšã£ãŠéèŠãªã€ãã³ãã§ããã¢ãã©ã€ã¶ã
x = 10;ãèŠããšã`x`ã«ã€ããŠæã£ãŠãã以åã®çµãèŸŒã¿æ å ±ããã¹ãŠç Žæ£ããªããã°ãªããŸããã`x`ã®åã¯ãä»£å ¥ãããå€ã®åïŒãã®å Žåã¯`Number`ïŒã«ç¢ºå®ããŸãããã®ç¡å¹åã¯æ£ç¢ºæ§ã®ããã«äžå¯æ¬ ã§ããéçºè ãããæ··ä¹±ããåå ã¯ãçµã蟌ãŸãã倿°ãã¯ããŒãžã£å ã§åä»£å ¥ãããããã«ãã£ãŠå€éšã§ã®çµã蟌ã¿ãç¡å¹ã«ãªãããšã§ãã - ã«ãŒãïŒ ã«ãŒãã¯CFGã«ãµã€ã¯ã«ãäœæããŸããã«ãŒãã®åæã¯ããè€éã§ããã¢ãã©ã€ã¶ã¯ã«ãŒãæ¬äœãåŠçããã«ãŒãã®çµããã®ç¶æ ãã«ãŒãã®å§ãŸãã®ç¶æ ã«ã©ã®ããã«åœ±é¿ãããã確èªããå¿ èŠããããŸããåæ å ±ãå®å®ãããŸã§ãã«ãŒãæ¬äœãè€æ°åååæããå¿ èŠããããããããŸããâããã¯äžåç¹ã«å°éããããã»ã¹ãšããŠç¥ãããŠããŸããäŸãã°ã`for...of`ã«ãŒãã§ã¯ã倿°ã®åã¯ã«ãŒãå ã§çµã蟌ãŸãããããããŸãããããã®çµã蟌ã¿ã¯åã€ãã¬ãŒã·ã§ã³ã§ãªã»ãããããŸãã
åºæ¬ãè¶ ããŠïŒé«åºŠãªCFAã®æŠå¿µãšèª²é¡
äžèšã®åçŽãªã¢ãã«ã¯åºæ¬ãã«ããŒããŠããŸãããçŸå®äžçã®ã·ããªãªã¯ããªãã®è€éãããããããŸãã
åè¿°èªãšãŠãŒã¶ãŒå®çŸ©ã®åã¬ãŒã
TypeScriptã®ãããªçŸä»£ã®èšèªã§ã¯ãéçºè ãCFAã·ã¹ãã ã«ãã³ããäžããããšãã§ããŸãããŠãŒã¶ãŒå®çŸ©ã®åã¬ãŒãã¯ãæ»ãå€ã®åãç¹å¥ãªåè¿°èªã§ãã颿°ã§ãã
function isUser(obj: any): obj is User {
return obj && typeof obj.name === 'string';
}
æ»ãå€ã®åobj is Userã¯åãã§ãã«ãŒã«æ¬¡ã®ããã«äŒããŸãïŒããã®é¢æ°ã`true`ãè¿ãå ŽåãåŒæ°`obj`ã`User`åã§ãããšä»®å®ããŠãããã
CFAãif (isUser(someVar)) { ... }ã«ééãããšã颿°ã®å
éšããžãã¯ãçè§£ããå¿
èŠã¯ãããŸãããã·ã°ããã£ãä¿¡é ŒããŸãããtrueããã¹ã§ã¯ã`someVar`ã`User`ã«çµã蟌ã¿ãŸããããã¯ãã¢ããªã±ãŒã·ã§ã³ã®ãã¡ã€ã³ã«åºæã®æ°ããçµã蟌ã¿ãã¿ãŒã³ãã¢ãã©ã€ã¶ã«æããæ¡åŒµå¯èœãªæ¹æ³ã§ãã
åå²ä»£å ¥ãšãšã€ãªã¢ã·ã³ã°ã®åæ
倿°ã®ã³ããŒãåç §ãäœæãããšã©ããªãã§ããããïŒCFAã¯ãããã®é¢ä¿ã远跡ããã®ã«ååè³¢ããªããã°ãªããŸãããããã¯ãšã€ãªã¢ã¹è§£æãšããŠç¥ãããŠããŸãã
const { kind, radius } = shape; // shapeã¯Circle | Square
if (kind === 'circle') {
// ããã§ã¯ã'kind'ã¯'circle'ã«çµã蟌ãŸããŸãã
// ããããã¢ãã©ã€ã¶ã¯'shape'ãä»ãCircleã§ããããšãç¥ã£ãŠããã§ããããïŒ
console.log(radius); // TSã§ã¯ãããã¯å€±æããŸãïŒ'radius'ã¯'shape'ã«ååšããªãå¯èœæ§ããããŸãã
}
äžèšã®äŸã§ã¯ãããŒã«ã«å®æ°kindãçµã蟌ãã§ããå
ã®`shape`ãªããžã§ã¯ããèªåçã«çµã蟌ãŸããããã§ã¯ãããŸãããããã¯ã`shape`ãä»ã®å Žæã§å代å
¥ãããå¯èœæ§ãããããã§ããããããããããã£ãçŽæ¥ãã§ãã¯ãããšãããŸããããŸãïŒ
if (shape.kind === 'circle') {
// ããã¯ããŸããããŸãïŒCFAã¯'shape'èªäœããã§ãã¯ãããŠããããšãç¥ã£ãŠããŸãã
console.log(shape.radius);
}
æŽç·ŽãããCFAã¯ã倿°ã ãã§ãªãã倿°ã®ããããã£ã远跡ãããšã€ãªã¢ã¹ããå®å šãã§ãããšãïŒäŸãã°ãå ã®ãªããžã§ã¯ãã`const`ã§åä»£å ¥ã§ããªãå Žåãªã©ïŒãçè§£ããå¿ èŠããããŸãã
ã¯ããŒãžã£ãšé«é颿°ã®åœ±é¿
颿°ãåŒæ°ãšããŠæž¡ãããããã¯ããŒãžã£ã芪ã¹ã³ãŒããã倿°ããã£ããã£ããããããšãå¶åŸ¡ãããŒã¯éç·åœ¢ã«ãªããåæãã¯ããã«é£ãããªããŸãããããèããŠã¿ãŠãã ããïŒ
function process(value: string | null) {
if (value === null) {
return;
}
// ãã®æç¹ã§ãCFAã¯'value'ãstringã§ããããšãç¥ã£ãŠããŸãã
setTimeout(() => {
// ã³ãŒã«ããã¯å
ã®ããã§ã®'value'ã®åã¯äœã§ããããïŒ
console.log(value.toUpperCase()); // ããã¯å®å
šã§ããïŒ
}, 1000);
}
ããã¯å®å šã§ããããïŒç¶æ³ã«ãããŸããããã°ã©ã ã®å¥ã®éšåã`setTimeout`ã®åŒã³åºããšãã®å®è¡ã®éã«`value`ã倿Žããå¯èœæ§ãããå Žåãçµã蟌ã¿ã¯ç¡å¹ã§ããTypeScriptãå«ãã»ãšãã©ã®åãã§ãã«ãŒã¯ãããã§ã¯ä¿å®çã§ããå¯å€ã¯ããŒãžã£å ã®ãã£ããã£ããã倿°ã¯å€æŽãããå¯èœæ§ããããšä»®å®ãããããå€åŽã®ã¹ã³ãŒãã§è¡ãããçµã蟌ã¿ã¯ã倿°ã`const`ã§ãªãéããã³ãŒã«ããã¯å ã§ã¯ãã°ãã°å€±ãããŸãã
`never`ã«ããç¶²çŸ æ§ãã§ãã¯
CFAã®æã匷åãªå¿çšã®1ã€ã¯ãç¶²çŸ æ§ãã§ãã¯ãå¯èœã«ããããšã§ãã`never`åã¯ã決ããŠçºçããªãã¯ãã®å€ã衚ããŸããå€å¥å¯èœãªå ±çšäœã«å¯Ÿãã`switch`æã§ã¯ãåã±ãŒã¹ãåŠçããã«ã€ããŠãCFAã¯åŠçãããã±ãŒã¹ãå·®ãåŒãããšã§å€æ°ã®åãçµã蟌ãã§ãããŸãã
function getArea(shape: Shape) { // Shapeã¯Circle | Square
switch (shape.kind) {
case 'circle':
// ããã§ã¯ãshapeã¯Circle
return Math.PI * shape.radius ** 2;
case 'square':
// ããã§ã¯ãshapeã¯Square
return shape.sideLength ** 2;
default:
// ããã§ã®'shape'ã®åã¯äœã§ããããïŒ
// ãã㯠(Circle | Square) - Circle - Square = never
const _exhaustiveCheck: never = shape;
return _exhaustiveCheck;
}
}
åŸã§`Shape`å ±çšäœã«`Triangle`ã远å ãããã®ããã®`case`ã远å ãå¿ããå Žåã`default`åå²ã«å°éå¯èœã«ãªããŸãããã®åå²ã§ã®`shape`ã®åã¯`Triangle`ã«ãªããŸãã`Triangle`ã`never`åã®å€æ°ã«ä»£å ¥ããããšãããšãã³ã³ãã€ã«æãšã©ãŒãçºçãã`switch`æããã¯ãç¶²çŸ çã§ãªãããšãå³åº§ã«èŠåããŠãããŸããããã¯ãäžå®å šãªããžãã¯ã«å¯Ÿããå ç¢ãªã»ãŒããã£ããããæäŸããCFAã§ãã
éçºè ã«ãšã£ãŠã®å®çšçãªæå³
CFAã®ååãçè§£ããããšã§ããã广çãªããã°ã©ãã«ãªãããšãã§ããŸããæ£ããã ãã§ãªããåãã§ãã«ãŒãšããŸãã飿ºãããã³ãŒããæžãããšãã§ããããæç¢ºãªã³ãŒããšåé¢é£ã®æŠããæžããããšã«ã€ãªãããŸãã
- äºæž¬å¯èœãªçµã蟌ã¿ã®ããã«`const`ã奜ãïŒ å€æ°ãåä»£å ¥ã§ããªãå Žåãã¢ãã©ã€ã¶ã¯ãã®åã«ã€ããŠãã匷åãªä¿èšŒãè¡ãããšãã§ããŸãã`let`ã®ä»£ããã«`const`ã䜿çšãããšãã¯ããŒãžã£ãå«ãããè€éãªã¹ã³ãŒãã«ããã£ãŠçµã蟌ã¿ãç¶æããã®ã«åœ¹ç«ã¡ãŸãã
- å€å¥å¯èœãªå ±çšäœãåãå ¥ããïŒ ããŒã¿æ§é ããªãã©ã«ããããã£ïŒ`kind`ã`type`ãªã©ïŒã§èšèšããããšã¯ãCFAã·ã¹ãã ã«æå³ãäŒããæãæç¢ºã§åŒ·åãªæ¹æ³ã§ãããããã®å ±çšäœã«å¯Ÿãã`switch`æã¯æç¢ºã§å¹ççã§ãããç¶²çŸ æ§ãã§ãã¯ãå¯èœã«ããŸãã
- ãã§ãã¯ãçŽæ¥çã«ä¿ã€ïŒ ãšã€ãªã¢ã·ã³ã°ã§èŠãããã«ããªããžã§ã¯ãã®ããããã£ãçŽæ¥ãã§ãã¯ããïŒ`obj.prop`ïŒæ¹ããããããã£ãããŒã«ã«å€æ°ã«ã³ããŒããŠããããã§ãã¯ããããããçµã蟌ã¿ã®ä¿¡é Œæ§ãé«ããªããŸãã
- CFAã念é ã«çœ®ããŠãããã°ããïŒ åãçµã蟌ãŸããŠããã¯ããªã®ã«åãšã©ãŒã«ééããå Žåãå¶åŸ¡ãããŒã«ã€ããŠèããŠã¿ãŠãã ããã倿°ã¯ã©ããã§åä»£å ¥ãããŸãããïŒã¢ãã©ã€ã¶ãå®å šã«çè§£ã§ããªãã¯ããŒãžã£å ã§äœ¿çšãããŠããŸããïŒãã®ã¡ã³ã¿ã«ã¢ãã«ã¯åŒ·åãªãããã°ããŒã«ã§ãã
çµè«ïŒåå®å šæ§ã®éããªãå®è·è
åçµã蟌ã¿ã¯çŽæçã§ãã»ãšãã©éæ³ã®ããã«æããããŸãããããã¯ã³ã³ãã€ã©çè«ã«ãããæ°å幎ã®ç ç©¶ã®ç£ç©ã§ãããå¶åŸ¡ãããŒè§£æãéããŠå®çŸãããŠããŸããããã°ã©ã ã®å®è¡ãã¹ã®ã°ã©ããæ§ç¯ããåãšããžã«æ²¿ã£ãŠããããŠãã¹ãŠã®åæµç¹ã§åæ å ±ã现å¿ã«è¿œè·¡ããããšã«ãããåãã§ãã«ãŒã¯é©ãã¹ãã¬ãã«ã®ç¥æ§ãšå®å šæ§ãæäŸããŸãã
CFAã¯ãå ±çšäœãã€ã³ã¿ãŒãã§ãŒã¹ã®ãããªæè»ãªåãæ±ããªãããããšã©ãŒãæ¬çªç°å¢ã«å°éããåã«ããããã£ããããããšãå¯èœã«ããéããªãå®è·è ã§ããããã¯éçåä»ãã峿 Œãªå¶çŽã®ã»ãããããåçã§æèãèªèããã¢ã·ã¹ã¿ã³ããžãšå€ããŸããæ¬¡ã«ãšãã£ã¿ã`if`ãããã¯å ã§å®ç§ãªãªãŒãã³ã³ããªãŒããæäŸãããã`switch`æã§æªåŠçã®ã±ãŒã¹ãèŠåããããããšãããããéæ³ã§ã¯ãªãããšãããªãã¯ç¥ã£ãŠããã§ãããâããã¯ãå¶åŸ¡ãããŒè§£æã®ãšã¬ã¬ã³ãã§åŒ·åãªããžãã¯ãæ©èœããŠããã®ã§ãã